/*
 * Copyright (C) 2017-2019 Alibaba Group Holding Limited
 */
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include "aos/hal/pcm.h"
#include "lsdmac.h"
#include "user_audio_config_for_lib.h"
#include "user_audio_config.h"
#include "api_implemented_by_user.h"
#include "user_audio_api.h"
#include "spi_flash.h"
#include "dmac_config.h"
#include "le501x.h"
#include "io_config.h"
// pcm
#define EXAMPLE_PCM_CH0            PA01
#define EXAMPLE_PCM_CH1            PA07

#define LS_FLASH_BASE_ADDR 0x18000000

DEF_DMA_CONTROLLER(dmac1_inst, DMAC1);

static struct user_audio_config_t user_audio_config_array[] = USER_AUDIO_CONFIG;
static volatile bool audio_play_cplt_flag;

struct audio_hw_config user_audio_hw_config = 
{
    .dmac_inst_ptr = &dmac1_inst,
    .dma_channel1 = 1,
    .dma_channel2 = 2,
    .timer_irq = ADTIM1_IRQn,
    .handshake = CH_LSADTIM1_UP,
    .timer_inst = LSADTIM,
};

uint8_t get_volume_setting(void)
{
    return AUDIO_PCM_VOLUME_DEFAULT;
}

void user_read_audio_data(uint32_t offset, uint8_t *buf, uint16_t length)
{
    spi_flash_quad_io_read(offset, buf, length);
}

static void user_audio_play_cplt_func(void *param)
{
    *(bool *)param = true;
}

int aos_audio_pcm_init(void)
{
    DMA_CONTROLLER_INIT(dmac1_inst);
    audio_hw_init(&user_audio_hw_config);
    adtim1_ch1_io_init(EXAMPLE_PCM_CH0, true, 0);
    adtim1_ch2_io_init(EXAMPLE_PCM_CH1, true, 0);
    return 0;
}

/*
 * Block write if free dma buffer not ready, otherwise,
 * please return after copied.
 *
 * Return writen length, or negative if failed.
 *
 */
int aos_audio_pcm_write(aos_audio_pcm_device_t *pcm, unsigned char *buffer, int nbytes)
{
    if (pcm == NULL || buffer == NULL) {
        return -1;
    }
    user_audio_config_array[0].length = nbytes;
    user_audio_config_array[0].base = (uint32_t)buffer - LS_FLASH_BASE_ADDR;
    audio_start(user_audio_config_array[0].base, user_audio_config_array[0].length, &user_audio_play_cplt_func, (void*)&audio_play_cplt_flag);
    return 0;
}

/*
 * close pcm device
 *
 * Return:
 *   0 -- success
 *  -1 -- failed
 *
 */
int aos_audio_pcm_close(aos_audio_pcm_device_t *pcm)
{
    if (pcm == NULL) {
        return -1;
    }
    // audio_stop();
    return 0;
}

